home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / mewin10s.zip / MSWINPUT.C < prev    next >
C/C++ Source or Header  |  1992-04-01  |  8KB  |  303 lines

  1. /* The routines in this file provide keyboard and mouse input support
  2.    under the Microsoft Windows environment on an IBM-PC or compatible
  3.    computer.
  4.  
  5.    Must be compiled with Borland C++ 2.0.
  6.  
  7.    It should not be compiled if the WINDOW_MSWIN symbol is not set */
  8.  
  9. #include    "estruct.h"
  10. #include    "elang.h"
  11. #include    <stdio.h>
  12. #include    <time.h>
  13. #include    "eproto.h"
  14. #include    "edef.h"
  15.  
  16. #include    "mswin.h"
  17.  
  18. #define IBUFSIZE    64      /* this must be a power of 2 */
  19.  
  20. static unsigned char in_buf[IBUFSIZE];  /* input character buffer */
  21. static int in_next = 0;                 /* pos to retrieve next input character */
  22. static int in_last = 0;                 /* pos to place most recent input character */
  23. static int in_free = 0;                 /* number of unused char entries */
  24.  
  25. static int vk_at = -1;                  /* VK code for '@' key */
  26.  
  27. /* in_init: initialize the input stream buffer */
  28. /* =======                                     */
  29.  
  30. void    in_init (void)
  31. {
  32.     /*-initialize input stream buffer */
  33.     in_next = in_last = 0;
  34.     in_free = IBUFSIZE;
  35.     
  36.     /*-initialize vk_at to try to support the popular ^@ */
  37.     vk_at = VkKeyScan ('@');
  38.     if (HIBYTE(vk_at) != 1) {
  39.         /* not a shifted key. no cigar! */
  40.         vk_at = -1;
  41.     }
  42. } /* in_init */
  43.  
  44. /* in_room: is there enough room for n chars ? */
  45. /* =======                                     */
  46.  
  47. BOOL    in_room (int n)
  48. {
  49.     if (n <= in_free) return TRUE;
  50.     else {
  51.         MessageBeep (0);
  52.     return FALSE;
  53.     }
  54. } /* in_room */
  55.  
  56. /* in_check:    is the input buffer non empty? */
  57. /* ========                                    */
  58.  
  59. BOOL    in_check (void)
  60. {
  61.     if (in_next == in_last)
  62.         return(FALSE);
  63.     else
  64.         return(TRUE);
  65. } /* in_check */
  66.  
  67. /* in_put:  enter an event into the input buffer */
  68. /* ======                                        */
  69.  
  70. void    in_put (int event)
  71. {
  72.     in_buf[in_last++] = event;
  73.     in_last &= (IBUFSIZE - 1);
  74.     --in_free;
  75. } /* in_put */
  76.  
  77. /* in_get:  get an event from the input buffer */
  78. /* ======                                      */
  79.  
  80. int in_get (void)
  81. {
  82.     register int event;    /* event to return */
  83.  
  84.     event = in_buf[in_next++];
  85.     in_next &= (IBUFSIZE - 1);
  86.     ++in_free;
  87.     return(event);
  88. } /* in_get */
  89.  
  90. /* typahead:    TRUE if there are typeahead characters in the input stream */
  91. /* ========                                                                */
  92.  
  93. PASCAL typahead (void)
  94. {
  95.     if (in_check()) return TRUE;
  96.     else return FALSE;
  97. } /* typahead */
  98.  
  99. /* EatKey: processes WM_(SYS)KEYxxx and WM_(SYS/MENU)CHAR messages */
  100. /* ======                                                          */
  101.  
  102. BOOL far pascal EatKey (WORD MsgCode, WORD Key, DWORD lParam)
  103.  
  104. /* This function must be called for each WM_(SYS)KEYxxx or
  105.    WM_(SYS/MENU)CHAR message. It returns TRUE if it has taken possesion
  106.    of the keyboard action. In that case, the message processing should
  107.    be terminated */
  108. {
  109.     WORD    evt = -1;       /* -1 means: key not for emacs */
  110.     WORD    prefix = 0;
  111.  
  112.     if (IsIconic (hFrameWnd)) return FALSE;   /* no input while fully
  113.                          iconic */
  114.     switch (MsgCode) {
  115.         
  116.     case WM_KEYDOWN:
  117. KeyDown:
  118.         /*-process the non-ascii keys (Page-up, Page-down, End, Home,
  119.        Arrows, Insert, Delete, function keys) */
  120.     prefix = SPEC;
  121.     if (GetKeyState (VK_CONTROL) < 0) prefix |= CTRL;
  122.     if (GetKeyState (VK_SHIFT) < 0) prefix |= SHFT;
  123.     switch (Key) {
  124.  
  125.     case VK_HOME:
  126.         evt = '<';
  127.         break;
  128.     case VK_UP:
  129.         evt = 'P';
  130.         break;
  131.     case VK_PRIOR:  /* Page-up */
  132.         evt = 'Z';
  133.         break;
  134.     case VK_LEFT:
  135.         evt = 'B';
  136.         break;
  137.     case VK_RIGHT:
  138.         evt = 'F';
  139.         break;
  140.     case VK_END:
  141.         evt = '>';
  142.         break;
  143.     case VK_DOWN:
  144.         evt = 'N';
  145.         break;
  146.     case VK_NEXT:   /* Page-down */
  147.         evt = 'V';
  148.         break;
  149.     case VK_INSERT:
  150.         evt = 'C';
  151.         break;
  152.     case VK_DELETE:
  153.         evt = 'D';
  154.         break;
  155.     default:
  156.         if ((Key >= VK_F1) && (Key <= VK_F10)) {    /* function key */
  157.         if (Key == VK_F10) evt = '0';
  158.         else evt = Key - VK_F1 + '1';
  159.         }
  160.         else if ((vk_at > 0) && (Key == LOBYTE(vk_at)) &&
  161.                      ((prefix & (SHFT | CTRL)) == CTRL)) {
  162.                 /* we assume a ^@ or A-^@ */
  163.                 prefix &= ALTD;
  164.                 evt = 0;
  165.             }
  166.         break;
  167.     }
  168.     break;
  169.  
  170.     case WM_SYSKEYDOWN:
  171.         /*-process ALT'ed function keys */
  172.         if (!(lParam & 0x20000000)) goto KeyDown;
  173.             /* for some reason, plain F10 arrives as a SYS message ! */
  174.         if (Key == VK_F4) return FALSE; /* standard accelerator for
  175.                        Frame's SC_CLOSE */
  176.         goto KeyDown;
  177.         
  178.     case WM_CHAR:
  179.         /*-process regular ASCII, with CTRL & SHFT embedded in event */ 
  180.     evt = Key;
  181.     break;
  182.  
  183.     case WM_SYSCHAR:
  184.         if (lParam & 0x20000000) {  /*-process ALT'ed ASCII char */
  185.         evt = upperc(Key);
  186.         prefix = ALTD;
  187.         if (getbind(ALTD | evt) == NULL) {
  188.             /* that key is not bound, let's ignore it to have
  189.            Windows check for a menu-bar accelerator */
  190.             evt = -1;
  191.         }
  192.     }
  193.     break;
  194.  
  195.     case WM_MENUCHAR:
  196.     if (!(LOWORD(lParam) & MF_POPUP) && (GetKeyState (VK_MENU) < 0)) {
  197.         /* it is an ALT'ed char that does not match any accelerator */
  198.         evt = upperc(Key);
  199.         prefix = ALTD;
  200.     }
  201.     break;
  202.     }
  203.     
  204.     if (evt == -1) return FALSE; /* nothing of interest ! */
  205.  
  206.     if (in_room (3)) {
  207.     if ((prefix != 0) || (evt == 0)) {
  208.         in_put (0);
  209.         in_put (prefix >> 8);
  210.     }
  211.     in_put (evt);
  212.     }
  213.     return TRUE;
  214. } /* EatKey */
  215.  
  216. /* PutMouseMessage: feeds a mouse message into the in_put queue */
  217. /* ===============                                              */
  218.  
  219. void pascal near    PutMouseMessage (WORD wMsg, WORD wParam, POINT Position)
  220.  
  221. {
  222.     char    c;
  223.     int     prefix;
  224.  
  225.     if (!mouseflag) return; /* mouse input is disabled */
  226.     
  227.     switch (wMsg) {
  228.     case WM_LBUTTONDOWN:
  229.     c = 'a';
  230.     break;
  231.     case WM_LBUTTONUP:
  232.     c = 'b';
  233.     break;
  234.     case WM_MBUTTONDOWN:
  235.     c = 'c';
  236.     break;
  237.     case WM_MBUTTONUP:
  238.     c = 'd';
  239.     break;
  240.     case WM_RBUTTONDOWN:
  241.     c = 'e';
  242.     break;
  243.     case WM_RBUTTONUP:
  244.     c = 'f';
  245.     break;
  246.     default:
  247.     return; /* should not happen, but let's be safe! */
  248.     }
  249.     prefix = MOUS;
  250.     if (wParam & (MK_CONTROL | MK_SHIFT)) {
  251.         c = toupper(c);
  252.         if (wParam & MK_CONTROL) prefix |= CTRL;
  253.     }
  254.     in_put (0);
  255.     in_put (prefix >> 8);
  256.     in_put ((unsigned char)Position.x);
  257.     in_put ((unsigned char)Position.y);
  258.     in_put (c);
  259. } /* PutMouseMessage */
  260.  
  261. /* MouseMessage:    handles client area mouse messages */
  262. /* ============                                        */
  263.  
  264. void far pascal MouseMessage (HWND hWnd, WORD wMsg, WORD wParam, DWORD lParam)
  265. {
  266.     POINT           Position;
  267.  
  268.     ClientToCell (hWnd, *(POINT*)&lParam, &Position);
  269.     
  270.     switch (wMsg) {
  271.     case WM_MOUSEMOVE:
  272.     if (MouseTracking && !notquiescent) {
  273.             MoveEmacsCaret (hWnd, Position.x, Position.y);
  274.         }
  275.     break;
  276.  
  277.     case WM_LBUTTONDOWN:
  278.     case WM_MBUTTONDOWN:
  279.     case WM_RBUTTONDOWN:
  280.         if (in_room (5) && mouseflag) {
  281.         PutMouseMessage (wMsg, wParam, Position);
  282.         MouseTracking = TRUE;
  283.         SetCapture (hWnd);
  284.         if (!notquiescent) MoveEmacsCaret (hWnd, Position.x, Position.y);
  285.     }
  286.     break;
  287.  
  288.     case WM_LBUTTONUP:
  289.     case WM_MBUTTONUP:
  290.     case WM_RBUTTONUP:
  291.         if (MouseTracking) {
  292.         if (in_room (5)) PutMouseMessage (wMsg, wParam, Position);
  293.         MouseTracking = FALSE;
  294.         ReleaseCapture ();  /* let go of the mouse */
  295.         if (!notquiescent) {
  296.                 MoveEmacsCaret (hWnd, CurrentCol, CurrentRow);
  297.                     /* restore the caret */
  298.             }
  299.     }
  300.     break;
  301.     }
  302. } /* MouseMessage */
  303.